package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.json.JSONUtil;
import com.aliyun.iot20180120.Client;
import com.aliyun.iot20180120.models.*;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zzyl.base.PageResponse;
import com.zzyl.dto.DeviceDto;
import com.zzyl.dto.DevicePageQueryDto;
import com.zzyl.entity.Device;
import com.zzyl.enums.BasicEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.DeviceMapper;
import com.zzyl.properties.AliIoTConfigProperties;
import com.zzyl.service.DeviceService;
import com.zzyl.vo.DeviceDataGraphVo;
import com.zzyl.vo.DeviceDataVo;
import com.zzyl.vo.DeviceVo;
import com.zzyl.vo.ProductVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class DeviceServiceimpl implements DeviceService {
    @Autowired
    private Client client;
    @Autowired
    private AliIoTConfigProperties aliIoTConfigProperties;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private DeviceMapper deviceMapper;

    /**
     * 同步产品列表
     */
    @Override
    public void syncProductList() {
        //创建查询产品列表的请求对象
        QueryProductListRequest queryProductListRequest = new QueryProductListRequest();
        queryProductListRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        queryProductListRequest.setCurrentPage(1);
        queryProductListRequest.setPageSize(100);
        QueryProductListResponse queryProductListResponse = null;
        try {
            // 查询公共产品列表
            queryProductListResponse = client.queryProductList(queryProductListRequest);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        if (queryProductListResponse.getBody().success) {
            List<QueryProductListResponseBody.QueryProductListResponseBodyDataListProductInfo> productInfo = queryProductListResponse.getBody().getData().list.getProductInfo();
            //将读取到的产品信息保存到Redis中
            redisTemplate.opsForValue().set("Device:product", JSONUtil.toJsonStr(productInfo));
        }
    }

    /**
     * 获取所有产品
     *
     * @return
     */
    @Override
    public List<ProductVo> allProduct() {
        // 从Redis中获取产品信息
        String s = redisTemplate.opsForValue().get("Device:product");
        // 将Redis中的字符串转换为List<ProductVo>
        List<ProductVo> productList = JSONUtil.toList(s, ProductVo.class);
        return productList;

    }

    /**
     * 注册设备
     *
     * @param deviceDto
     */
    @Override
    public void RegisterDevice(DeviceDto deviceDto) {
        //查看设备是否重复
        int count = deviceMapper.countByDeviceName(deviceDto.getDeviceName());
        if (count > 0) {
            throw new BaseException(BasicEnum.DEVICE_NAME_EXIST);
        }
        //新增设备
        RegisterDeviceRequest registerDeviceRequest = new RegisterDeviceRequest();
        registerDeviceRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        registerDeviceRequest.setDeviceName(deviceDto.getDeviceName());
        registerDeviceRequest.setProductKey(deviceDto.getProductKey());
        registerDeviceRequest.setNickname(deviceDto.getNickname());

        RegisterDeviceResponse registerDeviceResponse = null;
        try {
            registerDeviceResponse = client.registerDevice(registerDeviceRequest);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        if (!registerDeviceResponse.getBody().success) {
            throw new BaseException(BasicEnum.IOT_REGISTER_DEVICE_ERROR);
        }

        //将设备信息保存到数据库中
        Device device = BeanUtil.toBean(deviceDto, Device.class);
        device.setIotId(registerDeviceResponse.getBody().getData().getIotId());
        //从物联网平台查询产品名称
        QueryProductRequest queryProductRequest = new QueryProductRequest();
        queryProductRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        queryProductRequest.setProductKey(deviceDto.getProductKey());

        QueryProductResponse queryProductResponse = null;
        try {
            queryProductResponse = client.queryProduct(queryProductRequest);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        if (!queryProductResponse.getBody().success) {
            throw new BaseException(BasicEnum.IOT_QUERY_PRODUCT_ERROR);
        }
        device.setProductName(queryProductResponse.getBody().getData().getProductName());
        device.setHaveEntranceGuard(0);
        if (deviceDto.getLocationType().equals(0)){
            device.setPhysicalLocationType(-1);
        }

        try {
            deviceMapper.insert(device);
        } catch (Exception e) {
            DeleteDeviceRequest deleteDeviceRequest = new DeleteDeviceRequest();
            deleteDeviceRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
            deleteDeviceRequest.setIotId(device.getIotId());
            deleteDeviceRequest.setProductKey(device.getProductKey());
            deleteDeviceRequest.setDeviceName(device.getDeviceName());
            DeleteDeviceResponse deleteDeviceResponse = null;
            try {
                deleteDeviceResponse = client.deleteDevice(deleteDeviceRequest);
            } catch (Exception ex) {
                throw new RuntimeException(ex);
            }
            if (!deleteDeviceResponse.getBody().success) {
                throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
            }
        }

    }



    /**
     * 分页查询设备
     * @param devicePageQueryDto
     * @return
     */
    @Override
    public PageResponse<DeviceVo> pageQueryDevice(DevicePageQueryDto devicePageQueryDto) {
        PageHelper.startPage(devicePageQueryDto.getPageNum(),devicePageQueryDto.getPageSize());
        Page<DeviceVo> deviceVos = deviceMapper.selectByPage(devicePageQueryDto);
        return PageResponse.of(deviceVos,DeviceVo.class);

    }

    /**
     * 查询设备详情
     *
     * @param deviceDto
     * @return
     */
    @Override
    public DeviceVo queryDeviceDetail(DeviceDto deviceDto) {
        //根据产品唯一标识iotId查询设备详情
        DeviceVo deviceVo = deviceMapper.queryDeviceDetail(deviceDto.getIotId());
        //从公共产品列表中查询设备详情
        QueryDeviceDetailRequest request = new QueryDeviceDetailRequest();
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        request.setIotId(deviceDto.getIotId());
        request.setProductKey(deviceDto.getProductKey());
        QueryDeviceDetailResponse queryDeviceDetailResponse =null;
        try {
            queryDeviceDetailResponse = client.queryDeviceDetail(request);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        if (!queryDeviceDetailResponse.getBody().success){
            throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
        }
        QueryDeviceDetailResponseBody.QueryDeviceDetailResponseBodyData data = queryDeviceDetailResponse.getBody().getData();
        //将data查询到的设备详情合并到deviceDetail
        BeanUtil.copyProperties(data,deviceVo);
        return deviceVo;
    }

    /**
     * 查询指定设备的物模型运行状态
     * @param deviceDto
     * @return
     */
    @Override
    public QueryDevicePropertyStatusResponseBody.QueryDevicePropertyStatusResponseBodyData queryDevicePropertyStatus(DeviceDto deviceDto) {
        QueryDevicePropertyStatusRequest queryDevicePropertyStatusRequest = new QueryDevicePropertyStatusRequest();
        queryDevicePropertyStatusRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        queryDevicePropertyStatusRequest.setIotId(deviceDto.getIotId());
        queryDevicePropertyStatusRequest.setProductKey(deviceDto.getProductKey());
        queryDevicePropertyStatusRequest.setDeviceName(deviceDto.getDeviceName());
        QueryDevicePropertyStatusResponse queryDevicePropertyStatusResponse =null;
        try {
            queryDevicePropertyStatusResponse = client.queryDevicePropertyStatus(queryDevicePropertyStatusRequest);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        if (!queryDevicePropertyStatusResponse.getBody().success){
            throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
        }
        QueryDevicePropertyStatusResponseBody.QueryDevicePropertyStatusResponseBodyData data = queryDevicePropertyStatusResponse.getBody().getData();
        return data;
    }

    /**
     * 查看指定产品的已发布物模型中的功能定义详情
     * @param deviceDto
     * @return
     */
    @Override
    public Map<String, Object> queryThingModelPublished(DeviceDto deviceDto) {
        QueryThingModelPublishedRequest queryThingModelPublishedRequest = new QueryThingModelPublishedRequest();
        queryThingModelPublishedRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        queryThingModelPublishedRequest.setProductKey(deviceDto.getProductKey());

        QueryThingModelPublishedResponse queryThingModelPublishedResponse =null;
        try {
            queryThingModelPublishedResponse = client.queryThingModelPublished(queryThingModelPublishedRequest);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        if (!queryThingModelPublishedResponse.getBody().success){
            throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
        }
        String thingModelJson = queryThingModelPublishedResponse.getBody().getData().getThingModelJson();
        Map<String, Object> map = new HashMap<>();
        map.put("thingModelJson",thingModelJson);
        return map;
    }

    /**
     * 修改设备备注名称
     * @param deviceDto
     */
    @Override
    public void updateDevice(DeviceDto deviceDto) {
        //修改数据库
//        Device device = new Device();
//        BeanUtils.copyProperties(deviceDto, Device.class);
        Device device = BeanUtil.toBean(deviceDto, Device.class);
        deviceMapper.updateDevice(device);
        //修改阿里云
        BatchUpdateDeviceNicknameRequest request=new BatchUpdateDeviceNicknameRequest();
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());

        List<BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo> deviceNicknameInfo = new ArrayList<>();
        BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo deviceNicknameInfo2 = new BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo();
        deviceNicknameInfo2.setDeviceName(device.getDeviceName());
        deviceNicknameInfo2.setNickname(device.getNickname());
        deviceNicknameInfo2.setProductKey(device.getProductKey());
        deviceNicknameInfo.add(deviceNicknameInfo2);

        request.setDeviceNicknameInfo(deviceNicknameInfo);

        BatchUpdateDeviceNicknameResponse batchUpdateDeviceNicknameResponse =null;
        try {
            batchUpdateDeviceNicknameResponse = client.batchUpdateDeviceNickname(request);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        if (!batchUpdateDeviceNicknameResponse.getBody().success){
            throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
        }
    }

    /**
     * 删除设备
     * @param deviceDto
     */
    @Override
    public void deleteDevice(DeviceDto deviceDto) {
        //删除数据库
        Device bean = BeanUtil.toBean(deviceDto, Device.class);
        deviceMapper.deleteById(bean.getIotId());
        //删除阿里云
        DeleteDeviceRequest request=new DeleteDeviceRequest();
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        request.setProductKey(bean.getProductKey());
        request.setDeviceName(bean.getDeviceName());
        request.setIotId(bean.getIotId());
        DeleteDeviceResponse deleteDeviceResponse =null;
        try {
            deleteDeviceResponse = client.deleteDevice(request);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        if (!deleteDeviceResponse.getBody().success){
            throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
        }
    }



    /**
     * 按天统计查询指标数据
     * @param iotId
     * @param functionId
     * @param startTime
     * @param endTime
     * @return
     */

    @Override
    public List<DeviceDataGraphVo> queryDeviceDataListByDay(String iotId, String functionId, Long startTime, Long endTime) {
        LocalDateTime startDateTime = LocalDateTimeUtil.of(startTime);
        LocalDateTime endDateTime = LocalDateTimeUtil.of(endTime);
        List<DeviceDataGraphVo> deviceDataVos =  deviceMapper.queryDeviceDataListByDay(iotId,functionId,startDateTime,endDateTime);

        //转换为map
        Map<String, Double> map = deviceDataVos.stream().collect(Collectors.toMap(DeviceDataGraphVo::getDateTime, DeviceDataGraphVo::getDataValue));
        //构建一个24小时的集合
        List<DeviceDataGraphVo> deviceDataGraphVos = DeviceDataGraphVo.dayInstance(startDateTime);
        //遍历集合，如果map中有值，则赋值给deviceDataGraphVo
        deviceDataGraphVos.forEach(deviceDataGraphVo -> {
            Double put = map.get(deviceDataGraphVo.getDateTime());
            if (put != null) {
                deviceDataGraphVo.setDataValue(put);
            }
        });


        return deviceDataGraphVos;
    }

    /**
     * 按周统计查询指标数据
     * @param iotId
     * @param functionId
     * @param startTime
     * @param endTime
     * @return
     */
    @Override
    public List<DeviceDataGraphVo> queryDeviceDataListByWeek(String iotId, String functionId, Long startTime, Long endTime) {
        LocalDateTime startDateTime = LocalDateTimeUtil.of(startTime);
        LocalDateTime endDateTime = LocalDateTimeUtil.of(endTime);
        List<DeviceDataGraphVo> deviceDataVos =  deviceMapper.queryDeviceDataListByWeek(iotId,functionId,startDateTime,endDateTime);

        //转换为map
        Map<String, Double> map = deviceDataVos.stream().collect(Collectors.toMap(DeviceDataGraphVo::getDateTime, DeviceDataGraphVo::getDataValue));
        //构建一个7天的集合
        List<DeviceDataGraphVo> deviceDataGraphVos = DeviceDataGraphVo.weekInstance(startDateTime);
        //遍历集合，如果map中有值，则赋值给deviceDataGraphVo
        deviceDataGraphVos.forEach(deviceDataGraphVo -> {
            Double put = map.get(deviceDataGraphVo.getDateTime());
            if (put != null) {
                deviceDataGraphVo.setDataValue(put);
            }
        });


        return deviceDataGraphVos;
    }

}
